﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;

namespace WebRSSBuilder.Core
{
    public class RSSFeedXLinqController: IRSSFeedController
    {
        #region Constructor
        public RSSFeedXLinqController()
        {
        } 
        #endregion
        #region Load
        public RSSFeed LoadRss(string FileURI)
        {
            DateTime help;
            XElement root = XElement.Load(FileURI);
            RSSFeed Feed = new RSSFeed();
            XElement Channel = root.Element("channel");
            #region Loading properties
            Feed.FileName = FileURI;
            Feed.Title = GetElement(Channel, "title");
            Feed.Link = GetElement(Channel, "link");
            Feed.Description = GetElement(Channel, "description");
            Feed.Language = GetElement(Channel, "language");
            Feed.Copyright = GetElement(Channel, "copyright");
            Feed.ManagiongEditor = GetElement(Channel, "managingEditor");
            Feed.Webmaster = GetElement(Channel, "webMaster");
            Feed.PubDate = ((DateTime.TryParse(GetElement(Channel, "pubDate"), out help)) ? help : help);
            Feed.LastBuildDate = ((DateTime.TryParse(GetElement(Channel, "lastBuildDate"), out help)) ? help : help);
            Feed.Category = GetElement(Channel, "generator");
            Feed.Generator = GetElement(Channel, "title");
            Feed.Docs = GetElement(Channel, "docs");
            Feed.Ttl = GetElement(Channel, "ttl");
            Feed.Rating = GetElement(Channel, "rating");
            Feed.TextInput = GetElement(Channel, "textInput");
            Feed.SkipHours = GetElement(Channel, "skipHours");
            Feed.SkipDays = GetElement(Channel, "skipDays");
            Feed.Editor = GetElement(Channel, "editor");
            Feed.WebURL = GetElement(Channel, "webURL");
            Feed.Subject = GetElement(Channel, "subject");
            Feed.StyleSheet = GetElement(Channel, "styleSheet");
            Feed.StyleType = GetElement(Channel, "styleType");
            if (Channel.Element("image") != null)
            {
                Feed.ImgLink = GetElement(Channel.Element("image"), "link");
                Feed.ImgURL = GetElement(Channel.Element("image"), "url");
                Feed.ImgTitle = GetElement(Channel.Element("image"), "link");
            }
            if (Channel.Element("cloud") != null)
            {
                Feed.CloudDomain = GetElement(Channel.Element("cloud"), "domain");
                Feed.CloudPort = GetElement(Channel.Element("cloud"), "port");
                Feed.CloudPath = GetElement(Channel.Element("cloud"), "path");
                Feed.CloudRegisterProcedure = GetElement(Channel.Element("cloud"), "registerProcedure");
                Feed.CloudProtocol = GetElement(Channel.Element("cloud"), "protocol");
            }
            #endregion
            IEnumerable<XElement> items =
                from el in Channel.Elements("item")
                select el;
            foreach (XElement item in items)
            {
                Feed.Items.Add(LoadItem(item));
            }
            return Feed;
        }
        private RSSItem LoadItem(XElement x)
        {
            RSSItem item = new RSSItem();
            DateTime help;
            bool b;
            int i;
            item.Author = GetElement(x, "author");
            item.Category = GetElement(x, "category");
            item.Comments = GetElement(x, "comments");
            item.Description = GetElement(x, "description");
            if (x.Element("enclosure") != null)
            {
                item.EnclosureLength = GetAttribute(x.Element("enclosure"), "length");
                item.EnclosureType = GetAttribute(x.Element("enclosure"), "type");
                item.EnclosureUrl = GetAttribute(x.Element("enclosure"), "url");
            }
            item.GUID = GetElement(x, "guid");
            item.Link = GetElement(x, "link");
            item.PubDate = ((DateTime.TryParse(GetElement(x, "pubDate"), out help)) ? help : help);
            item.IsPermaLink = (bool.TryParse(GetElement(x, "isPermenentLink"), out b) ? b : true);
            item.Identifier = GetElement(x, "identifier");
            item.TimeOffset = (int.TryParse(GetElement(x, "timeOffset"), out i) ? i : 0);
            item.Title = GetElement(x, "title");
            item.Valid = GetElement(x, "valid");
            return item;

        } 
        #endregion
        #region Save
        public void SaveFeed(RSSFeed Feed)
        {
            var Channel = GenerateChannel(Feed);
            XDocument doc = new XDocument(
                     new XDeclaration("1.0", "utf-8", "yes"),
                     new XElement("rss",
                         new XAttribute("version", "2.0"),
                         new XElement(Channel)
                      ));
            doc.Save(Feed.FileName);


        }
        private XElement GenerateChannel(RSSFeed Feed)
        {
            XElement Channel = new XElement("channel");
            #region Saving Properties
            if (Feed.Category != null)
                Channel.Add(new XElement("category", Feed.Category));
            if (Feed.CloudDomain != null)
            {
                Channel.Add(new XElement("cloud", new XAttribute("domain", Feed.CloudDomain),
                    new XAttribute("port", Feed.CloudPort),
                    new XAttribute("registerProcedure", Feed.CloudRegisterProcedure),
                    new XAttribute("protocol", Feed.CloudProtocol)
                    ));
            }
            if (Feed.Copyright != null)
                Channel.Add(new XElement("copyright", Feed.Copyright));
            if (Feed.Description != null)
                Channel.Add(new XElement("description", Feed.Description));
            if (Feed.Docs != null)
                Channel.Add(new XElement("docs", Feed.Docs));
            if (Feed.Editor != null)
                Channel.Add(new XElement("editor", Feed.Editor));
            if (Feed.FtpSite != null)
                Channel.Add(new XElement("ftpSite", Feed.FtpSite));
            if (Feed.Generator != null)
                Channel.Add(new XElement("generator", Feed.Generator));
            if (Feed.ImgURL != null)
            {
                Channel.Add(new XElement("image", new XElement("url", Feed.ImgURL),
                new XElement("title", Feed.ImgTitle),
                new XElement("link", Feed.Link)));
            }
            if (Feed.CloudDomain != null)
            {
                Channel.Add(new XElement("cloud", new XElement("domain", Feed.CloudDomain),
                new XElement("port", Feed.CloudPort),
                new XElement("path", Feed.CloudPath),
                new XElement("registerProcedure", Feed.CloudRegisterProcedure),
                new XElement("protocol", Feed.CloudProtocol)));
            }
            if (Feed.Language != null)
                Channel.Add(new XElement("language", Feed.Language));
            if (Feed.LastBuildDate != DateTime.MinValue)
                Channel.Add(new XElement("lastBuildDate", Feed.LastBuildDate.ToString()));
            if (Feed.Link != null)
                Channel.Add(new XElement("link", Feed.Link));
            if (Feed.ManagiongEditor != null)
                Channel.Add(new XElement("managiongEditor", Feed.ManagiongEditor));
            if (Feed.PubDate != DateTime.MinValue)
                Channel.Add(new XElement("pubDate", Feed.PubDate));
            if (Feed.Rating != null)
                Channel.Add(new XElement("rating", Feed.Rating));
            if (Feed.SkipDays != null)
                Channel.Add(new XElement("skipDays", Feed.SkipDays));
            if (Feed.SkipHours != null)
                Channel.Add(new XElement("skipHours", Feed.SkipHours));
            if (Feed.StyleSheet != null)
                Channel.Add(new XElement("styleSheet", Feed.StyleSheet));
            if (Feed.StyleType != null)
                Channel.Add(new XElement("styleType", Feed.StyleType));
            if (Feed.Subject != null)
                Channel.Add(new XElement("subject", Feed.Subject));
            if (Feed.TextInput != null)
                Channel.Add(new XElement("textInput", Feed.TextInput));
            if (Feed.Title != null)
                Channel.Add(new XElement("title", Feed.Title));
            if (Feed.Ttl != null)
                Channel.Add(new XElement("ttl", Feed.Ttl));
            if (Feed.Webmaster != null)
                Channel.Add(new XElement("webMaster", Feed.Webmaster));
            if (Feed.WebURL != null)
                Channel.Add(new XElement("webURL", Feed.WebURL));
            if (Feed.Subject != null)
                Channel.Add(new XElement("subject", Feed.Subject));
           #endregion
            #region Saving Items
            foreach (var item in Feed.Items)
            {
                XElement RssItem = new XElement("item",
                             new XElement("title", item.Title),
                             new XElement("description", item.Description),
                             new XElement("pubDate", item.PubDate.ToString()),
                             new XElement("identifier", item.Identifier),
                             new XElement("isPermenantLink", item.IsPermaLink),
                             new XElement("link", item.Link),
                             new XElement("timeOffset", item.TimeOffset),
                             new XElement("valid", item.Valid),
                             new XElement("author", item.Author),
                             new XElement("category", item.Category),
                             new XElement("comment", item.Comments)
                             );
                if (item.EnclosureUrl != null)
                    RssItem.Add(new XElement("encloure", new XAttribute("url", item.EnclosureUrl),
                                                           new XAttribute("type", item.EnclosureType),
                                                           new XAttribute("length", item.EnclosureLength)
                                             )
                                );
                Channel.Add(RssItem);
            }
            #endregion
            return Channel;

        } 
        #endregion
        #region Helpers
        private string GetElement(XElement x, string ElementName)
        {
            XElement Element = x.Element(ElementName);
            return (Element == null ? null : Element.Value.Trim());
        }
        private string GetAttribute(XElement x, string ElementName)
        {
            string ElementValue = x.Element("channel").Attribute(ElementName).Value;
            return (ElementValue == null ? null : ElementValue.Trim());
        } 
        #endregion
    }
}
